home *** CD-ROM | disk | FTP | other *** search
/ Palm Utilities / Palm_Utilities_CD-ROM_2001_2001.iso / files / internet misc / GetTLE 1.0 / GetTLE.exe / Src / Main.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-26  |  12.7 KB  |  452 lines

  1. /*
  2.     GetTLE - Main.c - The main file for GetTLE
  3.     Copyright ⌐2000 Andreas Schneider
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18. */
  19.  
  20. //    With thanks to Neil Rhodes and Julie McKeehan for
  21. //    their invaluable book
  22. //    'Palm Programming: the Developer's Guide'
  23.  
  24. #include <PalmOS.h>                // all the system headers needed, except...
  25. #include <NetMgr.h>       // .. this one
  26. #include "GetTLERsc.h"        // application resource defines
  27. #include "debug.h"        // Allow debug output to go to a file/memo
  28. #include "URLsMemo.h"     // Allow a list of URLs to be saved as a memo
  29. #include "PSatDB.h"       // handles the PocketSat database
  30. #include "http.h"         // the HTTP connection to the webserver
  31. #include "alerts.h"       // the popup alerts
  32. #include "Util.h"         // Some convenience functions
  33. #include "Progress.h"     // Progress indicator
  34.  
  35. // We need some global variables for the socket routines
  36. // The socket routines are macros that use them when expanded
  37.  
  38. extern UInt16 AppNetRefnum;
  39. extern Int32 AppNetTimeout;
  40. Err    errno;
  41.  
  42. #define version20    0x02000000    // PalmOS 2.0 version number - we insist on it
  43.  
  44. #define CreatorID 'GTLE'  // registered exclusively to us
  45. #define PrefID 0 // the docs says'usually 0', so that's what we use
  46. #define Version 1 // is returned by PrefGetAppReferences()
  47.  
  48. // Make sure these are not smaller than the Max Characters
  49. // of the appropriate text entry fields
  50. #define MAX_URL_LEN 120
  51.  
  52. typedef struct
  53. {
  54.   Char URL[MAX_URL_LEN+1]; // allow for trailing \0
  55.   Boolean debugging_enabled;
  56. }
  57. PreferencesType;
  58.  
  59. static PreferencesType Prefs={0}; // our preferences
  60.  
  61. // Stuff we do when the application starts
  62. static Boolean StartApplication(void)
  63. {
  64.   Int16 result=0;
  65.   UInt16 pref_size=0;
  66.   
  67.   // first we initialize the Memopad debugging
  68.   InitDebugMessages();
  69.     // let's see if there is a save preference for the TLE location
  70.   pref_size=sizeof(Prefs);
  71.   result=PrefGetAppPreferences(CreatorID,PrefID,&Prefs,&pref_size,true);
  72.   if (result==noPreferenceFound)
  73.   {
  74.     // if there is no saved preference we use a default site
  75.     StrCopy(Prefs.URL,"www.celestrak.com/NORAD/elements/stations.txt");
  76.     Prefs.debugging_enabled=false;
  77.   }
  78.   if (Prefs.debugging_enabled)
  79.   {
  80.     StartDebugMessages();
  81.   }
  82.   // first read a list of sites and build up the popup list
  83.   ReadURLsMemo();
  84.   // if we debug to Memopad log some information
  85.   LogMessage("URL: %s\n",Prefs.URL);
  86.   // Now open the PocketSat database
  87.   OpenPSatDB();
  88.     return false;
  89. }
  90.  
  91. // Make sure that the operating system version is ok
  92. static Err RomVersionCompatible (UInt32 requiredVersion, UInt16 launchFlags)
  93. {
  94.     UInt32 romVersion;
  95.         
  96.     // Check that we have the minimum required version of the OS or later
  97.     FtrGet(sysFtrCreator, sysFtrNumROMVersion, &romVersion);
  98.     if (romVersion < requiredVersion)
  99.   {
  100.         // If the program was started from the launcher display a message
  101.         // If the program was started any other way be quiet
  102.         if ((launchFlags & (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp)) ==
  103.             (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp))
  104.       {
  105.             FrmAlert (RomIncompatibleAlert);
  106.             // OS 1.0 will continuously relaunch this app unless we switch to 
  107.             // another safe one.  The sysFileCDefaultApp is considered "safe".
  108.             if (romVersion < 0x02000000)
  109.             {
  110.                 AppLaunchWithCommand(sysFileCDefaultApp, sysAppLaunchCmdNormalLaunch, NULL);
  111.             }
  112.         }
  113.         // wrong version - return error code
  114.         return (sysErrRomIncompatible);
  115.     }
  116.   // everything is ok
  117.     return 0;
  118. }
  119.  
  120. // Called before the application stops
  121. static void StopApplication(void)
  122. {
  123.   // clean up:
  124.   // close the PocketSat database
  125.   ClosePSatDB();
  126.   // and write the debug messages to the memo
  127.   WriteDebugMessages();
  128.   return;
  129. }
  130.  
  131. static void ListDrawFunction(Int16 item_number, RectanglePtr bounds,Char **data)
  132. {
  133.   Char ellipse[]="...";
  134.   Char *text=SiteNames[item_number];
  135.   Int16 x=bounds->topLeft.x;
  136.   Int16 y=bounds->topLeft.y;
  137.   Int16 width=bounds->extent.x;
  138.   Int16 half_width=width/2;
  139.   Int16 draw_width=width;
  140.   Int16 text_len=StrLen(text);
  141.   Int16 chars_to_draw=text_len;
  142.   Int16 pixels=0;
  143.   UInt16 pos=0;
  144.   UInt16 left=0;
  145.   UInt16 right=0;
  146.   
  147.   // first find out if the site name fits the width
  148.   pixels=FntCharsWidth(text,text_len);
  149.   if (pixels<width)
  150.   {
  151.     // the easy case the whole string fits - draw it
  152.     WinDrawChars(text,chars_to_draw,x,y);
  153.   }
  154.   else
  155.   {
  156.     // doesn't find completely use ellipse in the middle
  157.     // adjust width for the '...'
  158.     width-=FntCharsWidth(ellipse,StrLen(ellipse));
  159.     // use up to half the remaining width for the text on the left
  160.     half_width=width/2;
  161.     // how many characters from the left make up just under half the width?
  162.     left=1; // We want at least one
  163.     // add characters until we'd exceed half the remaining width
  164.     for (pos=1;pos<text_len && FntCharsWidth(text,pos+1)<=half_width;pos++)
  165.     {
  166.       left++; // one more character that fits
  167.     }
  168.     // for the text on the right we can now use all the remaining pixels 
  169.     // I reuse the half_width variable - it's roughly half the width anyway
  170.     half_width=width-FntCharsWidth(text,pos); // Pos, not Pos+1, because of the Pos++ above
  171.     // how many characters from the right make up just under the remaining space
  172.     right=1; // at least one
  173.     // add characters until we'd exceed the remaining space
  174.     for (pos=text_len-2;pos>=0 && FntCharsWidth(text+pos,text_len-pos)<=half_width;pos--)
  175.     {
  176.       right++;
  177.     }
  178.     // First we draw 'Left' characters from the left
  179.     WinDrawChars(text,left,x,y);
  180.     // adjust x
  181.     x+=FntCharsWidth(text,left);
  182.     // draw the ellipse
  183.     WinDrawChars(ellipse,StrLen(ellipse),x,y);
  184.     // adjust x again
  185.     x+=FntCharsWidth(ellipse,StrLen(ellipse));
  186.     // now draw the stuff on the right
  187.     WinDrawChars(text+(text_len-right),right,x,y);
  188.   }
  189.   return;
  190. }
  191.  
  192. // Initialize the main form
  193. static void MainViewInit(void)
  194. {
  195.     FormPtr    frm;
  196.     ListPtr list;
  197.  
  198.     // Get a pointer to the main form.
  199.     frm = FrmGetActiveForm();
  200.     list=FrmGetObjectPtr(frm,FrmGetObjectIndex(frm,GetTLEMainSitesList));
  201.     // set the text in the entry fields to the right values
  202.     SetFieldTextFromString(GetTLEMainURLField,Prefs.URL);
  203.     // now take care of the list
  204.     LstSetListChoices(list,NULL,NumSites);
  205.     LstSetDrawFunction(list,ListDrawFunction);
  206.     // Clear the progress indicator
  207.     ClearProgress();
  208.     // Draw the form.
  209.     FrmEraseForm(frm);
  210.     FrmDrawForm(frm);
  211.     return;
  212. }
  213.  
  214. // returns (locked) text in a field object
  215. static char *GetLockedPtr(UInt16 objectID)
  216. {
  217.     FormPtr    frm = FrmGetActiveForm();
  218.     FieldPtr fld = FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, objectID));
  219.     MemHandle    h = FldGetTextHandle(fld);
  220.     
  221.     if (h)
  222.         return MemHandleLock(h);
  223.     else
  224.         return 0;
  225. }
  226.  
  227. // The main form got an event    
  228. static Boolean MainViewHandleEvent(EventPtr event)
  229. {
  230.     Boolean        handled;
  231.     UInt16 interfaceError;
  232.     Err    error;
  233.     UInt16 PrefLen=0;
  234.     Char *URL;
  235.     UInt16 TLEs=0;
  236.     Char Message[64];
  237.   FormPtr Form;
  238.  
  239.   // initially we haven't handled the event
  240.     handled = false;
  241.     // now we look at the event type
  242.     switch (event->eType)
  243.     {
  244.        case ctlSelectEvent:  // A control button was pressed and released.
  245.            if (event->data.ctlEnter.controlID == GetTLEMainSendButton)
  246.            {
  247.           // This was the 'Get' button - 
  248.                 if (SysLibFind( "Net.lib", &AppNetRefnum) == 0) 
  249.                 {
  250.                   LogMessage("Found NetLib\n");
  251.                   // lock the two text fields containing hostname and filename
  252.                     URL = GetLockedPtr(GetTLEMainURLField);
  253.                     // Make sure we actually were able to lock the fields
  254.                     if (!URL)
  255.                     {
  256.                         MyErrorFunc("Missing URL", NULL);
  257.                     }
  258.                     else  
  259.                     {
  260.                       LogMessage("Opening NetLib\n");
  261.                         error = NetLibOpen(AppNetRefnum, &interfaceError);
  262.                         if (interfaceError != 0) 
  263.                         {
  264.                             MyErrorFunc("NetLibOpen: interface error", NULL);
  265.                             NetLibClose(AppNetRefnum, true);
  266.                         } 
  267.                         else if (error == 0 || error == netErrAlreadyOpen) 
  268.                         {
  269.                           AppNetTimeout=SysTicksPerSecond()*10;
  270.                           LogMessage("Will request doc now\n");
  271.                           ClearProgress();
  272.                         TLEs=RequestDocument(URL);
  273.                         ClearProgress();
  274.                          StrIToA(Message,TLEs);
  275.                            StrCat(Message," TLE sets received.");
  276.                            MyStatusFunc(Message);
  277.                            LogMessage("%s\n",Message);
  278.                            if (TLEs>0)    
  279.                            {
  280.                               // that url worked - make it our preference
  281.                               // first copy the stuff to the Prefs
  282.                               StrCopy(Prefs.URL,URL);
  283.                               PrefLen=sizeof(Prefs);
  284.                               PrefSetAppPreferences(CreatorID,PrefID,Version,&Prefs,PrefLen,true);
  285.                           LogMessage("saved preferences %i bytes:\n",PrefLen);
  286.                               LogMessage("http://%s",Prefs.URL);
  287.                            }
  288.                            else
  289.                            {
  290.                              LogMessage("Receive failed: %i\n",errno);
  291.                            }
  292.                             NetLibClose(AppNetRefnum, false);    
  293.                        }
  294.                        else
  295.                        {
  296.                            MyErrorFunc("netLibOpen error", NULL);
  297.                     }
  298.                   }
  299.                    if (URL)
  300.                    {
  301.                      MemPtrUnlock(URL);
  302.                    }
  303.               }
  304.               else
  305.               {
  306.                   MyErrorFunc("Can't SysLibFind", NULL);
  307.               }
  308.               // Whatever the outcome - we have handled the event
  309.               handled = true;
  310.             }
  311.             else
  312.             {
  313.               // No other controls for this application
  314.             }
  315.             break;            
  316.         case frmOpenEvent:
  317.           // When the form gets opened we have to draw it
  318.             FrmDrawForm(FrmGetActiveForm());
  319.             // MainViewInit() sets the text fields with hostname and
  320.             // filename to the default or preferences values
  321.             MainViewInit();
  322.             handled = true;
  323.             break;
  324.         case popSelectEvent:
  325.             SetFieldTextFromString(GetTLEMainURLField,SiteUrls[event->data.popSelect.selection]);
  326.           handled = true;
  327.           break;
  328.         case menuEvent:
  329.         switch (event->data.menu.itemID)
  330.           {
  331.              case MainOptionsAboutGetTLE:
  332.                  MenuEraseStatus(0); // Clear the menu status from the display.
  333.                  Form = FrmInitForm (AboutForm);
  334.                  FrmDoDialog (Form); // Display the About Box.
  335.                   FrmDeleteForm (Form);
  336.                  handled = true;
  337.                  break;
  338.                case MainOptionsClearDatabase:
  339.                  MenuEraseStatus(0);
  340.                  ClearPSatDB();
  341.                  break;
  342.                case MainOptionsStartStopLogging:
  343.                  {
  344.                    Prefs.debugging_enabled=!Prefs.debugging_enabled;
  345.                    if (Prefs.debugging_enabled)
  346.                    {
  347.                      StartDebugMessages();
  348.                      MyStatusFunc("Now logging to Memo Pad");
  349.                    }
  350.                    else
  351.                    {
  352.                      StopDebugMessages();
  353.                      MyStatusFunc("Stopped logging to Memo Pad");
  354.                    }
  355.                    // this changes our preferences - save them
  356.                        PrefLen=sizeof(Prefs);
  357.                       PrefSetAppPreferences(CreatorID,PrefID,Version,&Prefs,PrefLen,true);
  358.                    LogMessage("saved preferences %i bytes:\n",PrefLen);
  359.                  }
  360.                  break;
  361.                default:
  362.                  break;
  363.           }
  364.             break;
  365.         default:
  366.           break;
  367.     }
  368.     return(handled);
  369. }
  370.  
  371. // Event handler for the application
  372. static Boolean ApplicationHandleEvent(EventPtr event)
  373. {
  374.     FormPtr    frm;
  375.     UInt16        formId;
  376.     Boolean    handled = false;
  377.  
  378.     if (event->eType == frmLoadEvent)
  379.     {
  380.         // Load the form resource specified in the event then activate the form.
  381.         formId = event->data.frmLoad.formID;
  382.         frm = FrmInitForm(formId);
  383.         FrmSetActiveForm(frm);
  384.         // tell the form about its event handler
  385.         switch (formId)
  386.         {
  387.             case GetTLEMainForm:
  388.                 FrmSetEventHandler(frm, MainViewHandleEvent);
  389.                 break;
  390.             default:
  391.               break;
  392.         }
  393.         handled = true;
  394.     }
  395.     return handled;
  396. }
  397.  
  398. // Standard stuff in here
  399. static void EventLoop(void)
  400. {
  401.     EventType    event;
  402.     UInt16 error;
  403.     
  404.     do
  405.     {
  406.         EvtGetEvent(&event, evtWaitForever);
  407.         if (! SysHandleEvent(&event))
  408.         {
  409.             if (! MenuHandleEvent(0, &event, &error))
  410.             {
  411.                 if (! ApplicationHandleEvent(&event))
  412.                 {
  413.                     FrmDispatchEvent(&event);
  414.                 }
  415.             }
  416.         }
  417.     }
  418.     while (event.eType != appStopEvent);
  419.     return;
  420. }
  421. // Standard stuff in here too
  422.  
  423. UInt32 PilotMain(UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags)
  424. {
  425.     UInt16 error;
  426.     
  427.     // Check the OS version
  428.     error = RomVersionCompatible (version20, launchFlags);
  429.     if (error)
  430.     {
  431.         return error;
  432.   }
  433.   // how was the application lauched?
  434.     if (cmd == sysAppLaunchCmdNormalLaunch)
  435.     {
  436.       // normal launch is the only way we do support
  437.       // try to initialize the application
  438.         if (!StartApplication())
  439.         {
  440.           // Now show the main form
  441.             FrmGotoForm(GetTLEMainForm);
  442.             // and start the event loop            
  443.             EventLoop();
  444.             // the event loop only quits for an appStopEvent
  445.             // so we try to stop the application
  446.             StopApplication();
  447.         }
  448.     }
  449.     // and that's the end of our program
  450.     return 0;
  451. }
  452.